import { Store } from "../../core";

import SelectionMode from "./SelectionMode";
import StoreProps from "./StoreProps";
import { FC, useEffect, useRef, useState } from "react";

const Tracker: FC<{
  store: Store<StoreProps>;
}> = ({ store }) => {
  const pagesRef = useRef<HTMLElement | null>(null);
  const [selectionMode, setSelectionMode] = useState<SelectionMode>(
    SelectionMode.Text
  );
  const pos = useRef({ top: 0, left: 0, x: 0, y: 0 });

  const onMouseMoveHandler = (e: MouseEvent): void => {
    const ele = pagesRef.current;
    if (!ele) {
      return;
    }

    ele.scrollTop = pos.current.top - (e.clientY - pos.current.y);
    ele.scrollLeft = pos.current.left - (e.clientX - pos.current.x);
  };

  const onMouseUpHandler = (): void => {
    const ele = pagesRef.current;
    if (!ele) {
      return;
    }

    ele.classList.add("rpv-selection-mode__grab");
    ele.classList.remove("rpv-selection-mode__grabbing");

    document.removeEventListener("mousemove", onMouseMoveHandler);
    document.removeEventListener("mouseup", onMouseUpHandler);
  };

  const onMouseDownHandler = (e: MouseEvent): void => {
    const ele = pagesRef.current;
    if (!ele || selectionMode === SelectionMode.Text) {
      return;
    }

    ele.classList.remove("rpv-selection-mode__grab");
    ele.classList.add("rpv-selection-mode__grabbing");

    e.preventDefault();
    e.stopPropagation();

    pos.current = {
      left: ele.scrollLeft,
      top: ele.scrollTop,
      x: e.clientX,
      y: e.clientY,
    };

    document.addEventListener("mousemove", onMouseMoveHandler);
    document.addEventListener("mouseup", onMouseUpHandler);
  };

  const handlePagesContainer = (getPagesContainer: () => HTMLElement) => {
    pagesRef.current = getPagesContainer();
  };

  const handleSelectionModeChanged = (mode: SelectionMode) => {
    setSelectionMode(mode);
  };

  useEffect(() => {
    const ele = pagesRef.current;
    if (!ele) {
      return;
    }

    selectionMode === SelectionMode.Hand
      ? ele.classList.add("rpv-selection-mode__grab")
      : ele.classList.remove("rpv-selection-mode__grab");

    ele.addEventListener("mousedown", onMouseDownHandler);
    return (): void => {
      ele.removeEventListener("mousedown", onMouseDownHandler);
    };
  }, [selectionMode]);

  useEffect(() => {
    store.subscribe("getPagesContainer", handlePagesContainer);
    store.subscribe("selectionMode", handleSelectionModeChanged);

    return (): void => {
      store.unsubscribe("getPagesContainer", handlePagesContainer);
      store.unsubscribe("selectionMode", handleSelectionModeChanged);
    };
  }, []);

  return <></>;
};

export default Tracker;
